home *** CD-ROM | disk | FTP | other *** search
/ Enter 2001 August / EnterCD8.iso / Internet / HTTrack Website Copier / httrack.exe / {app} / src / htscache.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-28  |  26.7 KB  |  835 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       cache system (index and stores files in cache)         */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. #include "htscache.h"
  39.  
  40. /* specific definitions */
  41. #include "htsbase.h"
  42. #include "htsbasenet.h"
  43. #include "htsmd5.h"
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. /* END specific definitions */
  48.  
  49.  
  50. // routines de mise en cache
  51.  
  52. /*
  53.   VERSION 1.0 :
  54.   -----------
  55.  
  56. .ndx file
  57.  file with data
  58.    <string>(date/time) [ <string>(hostname+filename) (datfile_position_ascii) ] * number_of_links
  59.  file without data
  60.    <string>(date/time) [ <string>(hostname+filename) (-datfile_position_ascii) ] * number_of_links
  61.  
  62. .dat file
  63.  [ file ] * 
  64. with
  65.   file= (with data)
  66.    [ bytes ] * sizeof(htsblk header) [ bytes ] * n(length of file given in htsblk header)
  67.  file= (without data)
  68.    [ bytes ] * sizeof(htsblk header)
  69. with
  70.  <string>(name) = <length in ascii>+<lf>+<data>
  71.  
  72.  
  73.   VERSION 1.1 :
  74.   -----------
  75.  
  76. .ndx file
  77.  file with data
  78.    <string>("CACHE-1.1") <string>(date/time) [ <string>(hostname+filename) (datfile_position_ascii) ] * number_of_links
  79.  file without data
  80.    <string>("CACHE-1.1") <string>(date/time) [ <string>(hostname+filename) (-datfile_position_ascii) ] * number_of_links
  81.  
  82. .dat file
  83.    <string>("CACHE-1.1") [ [Header_1.1] [bytes] * n(length of file given in header) ] *
  84. with
  85.  Header_1.1=
  86.    <int>(statuscode)
  87.    <int>(size)
  88.    <string>(msg)
  89.    <string>(contenttype)
  90.    <string>(last-modified)
  91.    <string>(Etag)
  92.    [<string>"SD" <string>(supplemental data)]
  93.    [<string>"SD" <string>(supplemental data)]
  94.    ...
  95.    <string>"HTS" (end of header)
  96.    <int>(number of bytes of data) (0 if no data written)
  97. */
  98.  
  99. // Nouveau: si != text/html ne stocke que la taille
  100.  
  101.  
  102. void cache_mayadd(httrackp* opt,cache_back* cache,htsblk* r,char* url_adr,char* url_fil,char* url_save) {
  103.   // ---stockage en cache---
  104.   // stocker dans le cache?
  105.   if (opt->cache) {
  106.     if (cache->dat!=NULL) {
  107.       // c'est le seul endroit ou l'on ajoute des elements dans le cache (fichier entier ou header)
  108.       // on stocke tout fichier "ok", mais Θgalement les rΘponses 404,301,302...
  109.       if ((r->statuscode==200)         /* stocker rΘponse standard, plus */
  110.         || (r->statuscode==204)     /* no content */
  111.         || (r->statuscode==301)     /* moved perm */
  112.         || (r->statuscode==302)     /* moved temp */
  113.         || (r->statuscode==303)     /* moved temp */
  114.         || (r->statuscode==307)     /* moved temp */
  115.         || (r->statuscode==401)     /* authorization */
  116.         || (r->statuscode==403)     /* unauthorized */
  117.         || (r->statuscode==404)     /* not found */
  118.         || (r->statuscode==410)     /* gone */
  119.         )
  120.       {        /* ne pas stocker si la page gΘnΘrΘe est une erreur */
  121.         if (!r->is_file) {
  122.           // stocker fichiers (et robots.txt)
  123.           if ( (strnotempty(url_save)) || (strcmp(url_fil,"/robots.txt")==0)) {
  124.             // ajouter le fichier au cache
  125.             cache_add(*r,url_adr,url_fil,url_save,cache->ndx,cache->dat,opt->all_in_cache);
  126.           }
  127.         }
  128.       }
  129.     }
  130.   }
  131.   // ---fin stockage en cache---
  132. }
  133.  
  134.  
  135. /* Ajout d'un fichier en cache */
  136. void cache_add(htsblk r,char* url_adr,char* url_fil,char* url_save,FILE* cache_ndx,FILE* cache_dat,int all_in_cache) {
  137.   int pos;
  138.   char s[256];
  139.   char buff[HTS_URLMAXSIZE*4];
  140.   int ok=1;
  141.   int dataincache=0;    // donnΘe en cache?
  142.   /*char digest[32+2];*/
  143.   /*digest[0]='\0';*/
  144.  
  145.   // Longueur url_save==0?
  146.   if ( (strnotempty(url_save)==0) ) {
  147.     if (strcmp(url_fil,"/robots.txt")==0)        // robots.txt
  148.       dataincache=1;
  149.     else
  150.       return;   // erreur (sauf robots.txt)
  151.   }
  152.  
  153.   if (r.size <= 0)   // taille <= 0 
  154.     return;          // refusΘ..
  155.  
  156.   // Mettre les *donΘes* en cache ?
  157.   if (is_hypertext_mime(r.contenttype))    // html, mise en cache des donnΘes et 
  158.     dataincache=1;                               // pas uniquement de l'en tΩte
  159.   else if (all_in_cache)
  160.     dataincache=1;                               // forcer tout en cache
  161.  
  162.   /* calcul md5 ? */
  163.   /*
  164.   if (is_hypertext_mime(r.contenttype)) {    // html, calcul MD5
  165.     if (r.adr) {
  166.       domd5mem(r.adr,r.size,digest,1,0);
  167.     }
  168.   }*/
  169.  
  170.   // Position
  171.   fflush(cache_dat); fflush(cache_ndx);
  172.   pos=ftell(cache_dat);
  173.   // Θcrire pointeur seek, adresse, fichier
  174.   if (dataincache)   // patcher
  175.     sprintf(s,"%d\n",pos);    // ecrire tel que (eh oui Θvite les \0..)
  176.   else
  177.     sprintf(s,"%d\n",-pos);   // ecrire tel que (eh oui Θvite les \0..)
  178.  
  179.   // data
  180.   // Θcrire donnΘes en-tΩte, donnΘes fichier
  181.   /*if (!dataincache) {   // patcher
  182.     r.size=-r.size;  // nΘgatif
  183.   }*/
  184.  
  185.   // Construction header
  186.   ok=0;
  187.   if (cache_wint(cache_dat,r.statuscode)!=-1)       // statuscode
  188.   if (cache_wLLint(cache_dat,r.size)!=-1)           // size
  189.   if (cache_wstr(cache_dat,r.msg)!=-1)              // msg
  190.   if (cache_wstr(cache_dat,r.contenttype)!=-1)      // contenttype
  191.   if (cache_wstr(cache_dat,r.lastmodified)!=-1)     // last-modified
  192.   if (cache_wstr(cache_dat,r.etag)!=-1)             // Etag
  193.   if (cache_wstr(cache_dat,(r.location!=NULL)?r.location:"")!=-1)         // 'location' pour moved
  194.   /*if (cache_wstr(cache_dat,"SD")!=-1)               // more data
  195.   if (cache_wstr(cache_dat,digest)!=-1)             // MD5 (version 
  196.   */
  197.   if (cache_wstr(cache_dat,"HTS")!=-1)              // end of header
  198.     ok=1;       /* ok */
  199.   // Fin construction header
  200.  
  201.   /*if ((int) fwrite((char*) &r,1,sizeof(htsblk),cache_dat) == sizeof(htsblk)) {*/
  202.   if (ok) {
  203.     if (dataincache) {    // mise en cache?
  204.       if (!r.adr) {       /* taille nulle (parfois en cas de 301 */
  205.         if (cache_wLLint(cache_dat,0)==-1)          /* 0 bytes */
  206.           ok=0;
  207.       } else if (r.is_write==0) {  // en mΘmoire, recopie directe
  208.         if (cache_wLLint(cache_dat,r.size)!=-1) {
  209.           if (r.size>0) {   // taille>0
  210.             if ((INTsys) fwrite(r.adr,1,(INTsys)r.size,cache_dat)!=r.size)
  211.               ok=0;
  212.           } else    // taille=0, ne rien Θcrire
  213.             ok=0;
  214.         } else
  215.           ok=0;
  216.       } else {  // recopier fichier dans cache
  217.         FILE* fp;
  218.         // On recopie le fichier..
  219.         LLint file_size=fsize(fconv(url_save));
  220.         if (file_size>=0) {
  221.           if (cache_wLLint(cache_dat,file_size)!=-1) {
  222.             fp=fopen(fconv(url_save),"rb");
  223.             if (fp!=NULL) {
  224.               char buff[32768];
  225.               int nl;
  226.               do {
  227.                 nl=fread(buff,1,32768,fp);
  228.                 if (nl>0) { 
  229.                   if ((INTsys) fwrite(buff,1,(INTsys)nl,cache_dat)!=nl) {  // erreur
  230.                     nl=-1;
  231.                     ok=0;
  232.                   }
  233.                 }
  234.               } while(nl>0);
  235.               fclose(fp);
  236.             } else ok=0;
  237.           } else ok=0;
  238.         } else ok=0;
  239.       }
  240.     } else {
  241.       if (cache_wLLint(cache_dat,0)==-1)          /* 0 bytes */
  242.         ok=0;
  243.     }
  244.   } else ok=0;
  245.   /*if (!dataincache) {   // dΘpatcher
  246.     r.size=-r.size;
  247.   }*/
  248.  
  249.   // index
  250.   // adresse+cr+fichier+cr
  251.   if (ok) {
  252.     buff[0]='\0'; strcat(buff,url_adr); strcat(buff,"\n"); strcat(buff,url_fil); strcat(buff,"\n");
  253.     cache_wstr(cache_ndx,buff);
  254.     fwrite(s,1,strlen(s),cache_ndx);
  255.   }  // si ok=0 on a peut Ωtre Θcrit des donnΘes pour rien mais on s'en tape
  256.   
  257.   // en cas de plantage, on aura au moins le cache!
  258.   fflush(cache_dat); fflush(cache_ndx);
  259. }
  260.  
  261.  
  262. // lecture d'un fichier dans le cache
  263. // si save==null alors test unqiquement
  264. htsblk cache_read(httrackp* opt,cache_back* cache,char* adr,char* fil,char* save) {
  265. #if HTS_FAST_CACHE
  266.   long int hash_pos;
  267.   int hash_pos_return;
  268. #else
  269.   char* a;
  270. #endif
  271.   char buff[HTS_URLMAXSIZE*2];
  272.   static char location[HTS_URLMAXSIZE*2];
  273.   htsblk r;
  274.   int ok=0;
  275.   int header_only=0;
  276.  
  277.   bzero((char *)&r, sizeof(htsblk)); r.soc=INVALID_SOCKET; strcpy(location,""); r.location=location;
  278. #if HTS_FAST_CACHE
  279.   strcpy(buff,adr); strcat(buff,fil);
  280.   hash_pos_return=inthash_read((hash_chain**)cache->hash,cache->hash_size,buff,(long int*)&hash_pos);
  281. #else
  282.   buff[0]='\0'; strcat(buff,"\n"); strcat(buff,adr); strcat(buff,"\n"); strcat(buff,fil); strcat(buff,"\n");
  283.   if (cache->use)
  284.     a=strstr(cache->use,buff);
  285.   else
  286.     a=NULL;       // forcer erreur
  287. #endif
  288.  
  289.   // en cas de succΦs
  290. #if HTS_FAST_CACHE
  291.   if (hash_pos_return) {
  292. #else
  293.   if (a!=NULL) {  // OK existe en cache!
  294. #endif
  295.     int pos;
  296. #if DEBUGCA
  297.     fprintf(stdout,"..cache: %s%s at ",adr,fil);
  298. #endif
  299.     
  300. #if HTS_FAST_CACHE
  301.     pos=hash_pos;     /* simply */
  302. #else
  303.     a+=strlen(buff);
  304.     sscanf(a,"%d",&pos);    // lire position
  305. #endif
  306. #if DEBUGCA
  307.     printf("%d\n",pos);
  308. #endif
  309.  
  310.     fflush(cache->olddat); 
  311.     if (fseek(cache->olddat,((pos>0)?pos:(-pos)),SEEK_SET) == 0) {
  312.       /* Importer cache1.0 */
  313.       if (cache->version==0) {
  314.         OLD_htsblk old_r;
  315.         if (fread((char*) &old_r,1,sizeof(old_r),cache->olddat)==sizeof(old_r)) { // lire tout (y compris statuscode etc)
  316.           r.statuscode=old_r.statuscode;
  317.           r.size=old_r.size;        // taille fichier
  318.           strcpy(r.msg,old_r.msg);
  319.           strcpy(r.contenttype,old_r.contenttype);
  320.           ok=1;     /* import  ok */
  321.         }
  322.       /* */
  323.       /* Cache 1.1 */
  324.       } else {
  325.         char check[256];
  326.         LLint size_read;
  327.         check[0]='\0';
  328.         //
  329.         cache_rint(cache->olddat,&r.statuscode);
  330.         cache_rLLint(cache->olddat,&r.size);
  331.         cache_rstr(cache->olddat,r.msg);
  332.         cache_rstr(cache->olddat,r.contenttype);
  333.         cache_rstr(cache->olddat,r.lastmodified);
  334.         cache_rstr(cache->olddat,r.etag);
  335.         cache_rstr(cache->olddat,r.location);
  336.         cache_rstr(cache->olddat,check);
  337.         /*if (strcmp(check,"SD")==0) {        // version 1.110: md5
  338.           cache_rstr(cache->olddat,r.digest);
  339.           cache_rstr(cache->olddat,check);
  340.         }*/
  341.         if (strcmp(check,"HTS")==0) {           /* intΘgritΘ OK */
  342.           ok=1;
  343.         }
  344.         cache_rLLint(cache->olddat,&size_read);       /* lire size pour Ωtre s√r de la taille dΘclarΘe (rΘΘcrire) */
  345.         if (size_read>0) {                         /* si inscrite ici */
  346.           r.size=size_read;
  347.         } else {                              /* pas de donnΘes directement dans le cache, fichier prΘsent? */
  348.           if (r.statuscode!=200)
  349.             header_only=1;          /* que l'en tΩte ici! */
  350.         }
  351.       }
  352.  
  353.       /* Remplir certains champs */
  354.       r.totalsize=r.size;
  355.  
  356.       // lecture du header (y compris le statuscode)
  357.       /*if (fread((char*) &r,1,sizeof(htsblk),cache->olddat)==sizeof(htsblk)) { // lire tout (y compris statuscode etc)*/
  358.       if (ok) {
  359.         // sΘcuritΘ
  360.         r.adr=NULL;
  361.         r.out=NULL;
  362.         ////r.location=NULL;  non, fixΘe lors des 301 ou 302
  363.         r.fp=NULL;
  364.         
  365.         if ( (r.statuscode>=0) && (r.statuscode<=999)
  366.           && (r.notmodified>=0)  && (r.notmodified<=9) ) {   // petite vΘrif intΘgritΘ
  367.           if ((save) && (!header_only) ) {     /* ne pas lire uniquement header */
  368.             //int to_file=0;
  369.             
  370.             r.adr=NULL; r.soc=INVALID_SOCKET; 
  371.             // // r.location=NULL;
  372.             
  373. #if HTS_DIRECTDISK
  374.             // Court-circuit:
  375.             // Peut-on stocker le fichier directement sur disque?
  376.             if ((r.statuscode==200) && (!is_hypertext_mime(r.contenttype)) && (strnotempty(save))) {    // pas HTML, Θcrire sur disk directement
  377.               int ok=0;
  378.               
  379.               r.is_write=1;    // Θcrire
  380.               if (fexist(antislash(save))) {  // un fichier existe dΘja
  381.                 //if (fsize(antislash(save))==r.size) {  // mΩme taille -- NON tant pis (taille mal declaree)
  382.                 ok=1;    // plus rien α faire
  383.                 filenote(save,NULL);        // noter comme connu
  384.                 //}
  385.               }
  386.               
  387.               if ((pos<0) && (!ok)) { // Pas de donnΘe en cache et fichier introuvable : erreur!
  388.                 if (opt->norecatch) {
  389.                   FILE* fp;
  390.                   fp=filecreate(save);
  391.                   if (fp) fclose(fp);
  392.                   //
  393.                   r.statuscode=-1;
  394.                   strcpy(r.msg,"File deleted by user not recaught");
  395.                   ok=1;     // ne pas rΘcupΘrer (et pas d'erreur)
  396.                 } else {
  397.                   r.statuscode=-1;
  398.                   strcpy(r.msg,"Previous cache file not found");
  399.                   ok=1;    // ne pas rΘcupΘrer
  400.                 }
  401.               }
  402.               
  403.               if (!ok) {  
  404.                 r.out=filecreate(save);
  405. #if HDEBUG
  406.                 printf("direct-disk: %s\n",save);
  407. #endif
  408.                 if (r.out!=NULL) {
  409.                   char buff[32768+4];
  410.                   LLint nl;
  411.                   LLint size;
  412.                   size=r.size;
  413.                   do {
  414.                     nl=fread(buff,1,(INTsys) minimum(size,32768),cache->olddat);
  415.                     if (nl>0) {
  416.                       size-=nl; 
  417.                       if ((INTsys) fwrite(buff,1,(INTsys)nl,r.out)!=nl) {  // erreur
  418.                         r.statuscode=-1;
  419.                         strcpy(r.msg,"Cache Read Error : Read To Disk");
  420.                       }
  421.                     }
  422.                   } while((nl>0) && (size>0) && (r.statuscode!=-1));
  423.                   
  424.                   fclose(r.out);
  425.                   r.out=NULL;
  426. #if HTS_WIN==0
  427.                   chmod(save,HTS_ACCESS_FILE);      
  428. #endif          
  429.                   usercommand(0,NULL,antislash(save));
  430.                 } else {
  431.                   r.statuscode=-1;
  432.                   strcpy(r.msg,"Cache Write Error : Unable to Create File");
  433.                   //printf("%s\n",save);
  434.                 }
  435.               }
  436.               
  437.             } else
  438. #endif
  439.             { // lire en mΘmoire
  440.               
  441.               if (pos<0) { // Pas de donnΘe en cache, bizzard car html!!!
  442.                 r.statuscode=-1;
  443.                 strcpy(r.msg,"Previous cache file not found (2)");
  444.               } else {
  445.                 // lire fichier (d'un coup)
  446.                 r.adr=(char*) malloct((INTsys)r.size+4);
  447.                 if (r.adr!=NULL) {
  448.                   if ((INTsys) fread(r.adr,1,(INTsys)r.size,cache->olddat)!=r.size) {  // erreur
  449.                     freet(r.adr);
  450.                     r.adr=NULL;
  451.                     r.statuscode=-1;
  452.                     strcpy(r.msg,"Cache Read Error : Read Data");
  453.                   }
  454.                   //printf(">%s status %d\n",back[p].r.contenttype,back[p].r.statuscode);
  455.                 } else {  // erreur
  456.                   r.statuscode=-1;
  457.                   strcpy(r.msg,"Cache Memory Error");
  458.                 }
  459.               }
  460.             }
  461.           }    // si save==null, ne rien charger (juste en tΩte)
  462.         } else {
  463. #if DEBUGCA
  464.           printf("Cache Read Error : Bad Data");
  465. #endif
  466.           r.statuscode=-1;
  467.           strcpy(r.msg,"Cache Read Error : Bad Data");
  468.         }
  469.       } else {  // erreur
  470. #if DEBUGCA
  471.         printf("Cache Read Error : Read Header");
  472. #endif
  473.         r.statuscode=-1;
  474.         strcpy(r.msg,"Cache Read Error : Read Header");
  475.       }
  476.     } else {
  477. #if DEBUGCA
  478.       printf("Cache Read Error : Seek Failed");
  479. #endif
  480.       r.statuscode=-1;
  481.       strcpy(r.msg,"Cache Read Error : Seek Failed");
  482.     }
  483.   } else {
  484. #if DEBUGCA
  485.     printf("File Cache Not Found");
  486. #endif
  487.     r.statuscode=-1;
  488.     strcpy(r.msg,"File Cache Not Found");
  489.   }
  490.   return r;
  491. }
  492.  
  493. /* write (string1-string2)-data in cache */
  494. /* 0 if failed */
  495. int cache_writedata(FILE* cache_ndx,FILE* cache_dat,char* str1,char* str2,char* outbuff,int len) {
  496.   if (cache_dat) {
  497.     char buff[HTS_URLMAXSIZE*4];
  498.     char s[256];
  499.     int pos;
  500.     fflush(cache_dat); fflush(cache_ndx);
  501.     pos=ftell(cache_dat);
  502.     /* first write data */
  503.     if (cache_wint(cache_dat,len)!=-1) {       // length
  504.       if ((INTsys) fwrite(outbuff,1,(INTsys)len,cache_dat) == (INTsys) len) {   // data
  505.         /* then write index */
  506.         sprintf(s,"%d\n",pos);
  507.         buff[0]='\0'; strcat(buff,str1); strcat(buff,"\n"); strcat(buff,str2); strcat(buff,"\n");
  508.         cache_wstr(cache_ndx,buff);
  509.         if (fwrite(s,1,strlen(s),cache_ndx) == strlen(s)) {
  510.           fflush(cache_dat); fflush(cache_ndx);
  511.           return 1;
  512.         }
  513.       }
  514.     }
  515.   }
  516.   return 0;
  517. }
  518.  
  519. /* read the data corresponding to (string1-string2) in cache */
  520. /* 0 if failed */
  521. int cache_readdata(cache_back* cache,char* str1,char* str2,char** inbuff,int* inlen) {
  522. #if HTS_FAST_CACHE
  523.   if (cache->hash) {
  524.     char buff[HTS_URLMAXSIZE*4];
  525.     long int pos;
  526.     strcpy(buff,str1); strcat(buff,str2);
  527.     if (inthash_read((hash_chain**)cache->hash,cache->hash_size,buff,(long int*)&pos)) {
  528.       if (fseek(cache->olddat,((pos>0)?pos:(-pos)),SEEK_SET) == 0) {
  529.         int len;
  530.         cache_rint(cache->olddat,&len);
  531.         if (len>0) {
  532.           char* mem_buff=(char*)malloc(len+4);    /* Plus byte 0 */
  533.           if (mem_buff) {
  534.             if ((int)fread(mem_buff,1,len,cache->olddat)==len) { // lire tout (y compris statuscode etc)*/
  535.               *inbuff=mem_buff;
  536.               *inlen=len;
  537.               return 1;
  538.             } else
  539.               free(mem_buff);
  540.           }
  541.         }
  542.       }
  543.     }
  544.   }
  545. #endif
  546.   *inbuff=NULL;
  547.   *inlen=0;
  548.   return 0;
  549. }
  550.  
  551. // renvoyer uniquement en tΩte, ou NULL si erreur
  552. htsblk* cache_header(httrackp* opt,cache_back* cache,char* adr,char* fil) {
  553.   static htsblk r;
  554.   r=cache_read(opt,cache,adr,fil,NULL);              // test uniquement
  555.   if (r.statuscode != -1)
  556.     return &r;
  557.   else
  558.     return NULL;
  559. }
  560.  
  561.           
  562. // Initialisation du cache: crΘer nouveau, renomer ancien, charger..
  563. void cache_init(cache_back* cache,httrackp* opt) {
  564.   // ---
  565.   // utilisation du cache: renommer ancien Θventuel et charger index
  566.   if (opt->cache) {
  567. #if DEBUGCA
  568.     printf("cache init: ");
  569. #endif
  570. #if HTS_WIN
  571.     mkdir(fconcat(opt->path_log,"hts-cache"));
  572. #else
  573.     mkdir(fconcat(opt->path_log,"hts-cache"),HTS_PROTECT_FOLDER);
  574. #endif
  575.     if ((fexist(fconcat(opt->path_log,"hts-cache/new.dat"))) && (fexist(fconcat(opt->path_log,"hts-cache/new.ndx")))) {  // il existe dΘja un cache prΘcΘdent.. renommer
  576. #if DEBUGCA
  577.       printf("work with former cache\n");
  578. #endif
  579.       if (fexist(fconcat(opt->path_log,"hts-cache/old.dat")))
  580.         remove(fconcat(opt->path_log,"hts-cache/old.dat"));
  581.       if (fexist(fconcat(opt->path_log,"hts-cache/old.ndx")))
  582.         remove(fconcat(opt->path_log,"hts-cache/old.ndx"));
  583.       
  584.       rename(fconcat(opt->path_log,"hts-cache/new.dat"),fconcat(opt->path_log,"hts-cache/old.dat"));
  585.       rename(fconcat(opt->path_log,"hts-cache/new.ndx"),fconcat(opt->path_log,"hts-cache/old.ndx"));
  586.     } else {  // un des deux (ou les deux) fichiers cache absents: effacer l'autre Θventuel
  587. #if DEBUGCA
  588.       printf("new cache\n");
  589. #endif
  590.       if (fexist(fconcat(opt->path_log,"hts-cache/new.dat")))
  591.         remove(fconcat(opt->path_log,"hts-cache/new.dat"));
  592.       if (fexist(fconcat(opt->path_log,"hts-cache/new.ndx")))
  593.         remove(fconcat(opt->path_log,"hts-cache/new.ndx"));
  594.     }
  595.     
  596.     // charger index cache prΘcΘdent
  597.     if ((fexist(fconcat(opt->path_log,"hts-cache/old.dat"))) && (fexist(fconcat(opt->path_log,"hts-cache/old.ndx")))) {  // cache prΘcΘdent
  598.       if ((fsize(fconcat(opt->path_log,"hts-cache/old.dat"))>=0) && (fsize(fconcat(opt->path_log,"hts-cache/old.ndx"))>0)) {
  599.         FILE* oldndx=NULL;
  600. #if DEBUGCA
  601.         printf("..load cache\n");
  602. #endif
  603.         cache->olddat=fopen(fconcat(opt->path_log,"hts-cache/old.dat"),"rb");        
  604.         oldndx=fopen(fconcat(opt->path_log,"hts-cache/old.ndx"),"rb");        
  605.         // les deux doivent Ωtre ouvrables
  606.         if ((cache->olddat==NULL) && (oldndx!=NULL)) {
  607.           fclose(oldndx);
  608.           oldndx=NULL;
  609.         }
  610.         if ((cache->olddat!=NULL) && (oldndx==NULL)) {
  611.           fclose(cache->olddat);
  612.           cache->olddat=NULL;
  613.         }
  614.         // lire index
  615.         if (oldndx!=NULL) {
  616.           int buffl;
  617.           fclose(oldndx); oldndx=NULL;
  618.           // lire ndx, et lastmodified
  619.           buffl=fsize(fconcat(opt->path_log,"hts-cache/old.ndx"));
  620.           cache->use=lirefichier(fconcat(opt->path_log,"hts-cache/old.ndx"));
  621.           if (cache->use!=NULL) {
  622.             char firstline[256];
  623.             char* a=cache->use;
  624.             a+=cache_brstr(a,firstline);
  625.             if (strncmp(firstline,"CACHE-",6)==0) {       // Nouvelle version du cache
  626.               if (strncmp(firstline,"CACHE-1.1",9)==0) {     // Version 1.1x
  627.                 cache->version=1;      // cache 1.1
  628.                 a+=cache_brstr(a,firstline);
  629.                 strcpy(cache->lastmodified,firstline); 
  630.               } else {        // non supportΘ
  631.                 if (opt->errlog) {
  632.                   fspc(opt->errlog,"error"); fprintf(opt->errlog,"Cache: %s not supported, ignoring current cache"LF,firstline);
  633.                   fflush(opt->errlog);
  634.                 }
  635.                 fclose(cache->olddat);
  636.                 cache->olddat=NULL;
  637.                 freet(cache->use);
  638.                 cache->use=NULL;
  639.               }
  640.               /* */
  641.             } else {              // Vieille version du cache
  642.               /* */
  643.               if (opt->log) {
  644.                 fspc(opt->log,"warning"); fprintf(opt->log,"Cache: importing old cache format"LF);
  645.                 fflush(opt->log);
  646.               }
  647.               cache->version=0;        // cache 1.0
  648.               strcpy(cache->lastmodified,firstline); 
  649.             }
  650.             opt->is_update=1;        // signaler comme update
  651.  
  652.             /* Create hash table for the cache (MUCH FASTER!) */
  653. #if HTS_FAST_CACHE
  654.             if (cache->use) {
  655.               char line[HTS_URLMAXSIZE*2];
  656.               char linepos[256];
  657.               int  pos;
  658.               while ( (a!=NULL) && (((int) a) < ((int)(cache->use+buffl))) ) {
  659.                 a=strchr(a+1,'\n');     /* start of line */
  660.                 if (a) {
  661.                   a++;
  662.                   /* read "host/file" */
  663.                   a+=binput(a,line,HTS_URLMAXSIZE);
  664.                   a+=binput(a,line+strlen(line),HTS_URLMAXSIZE);
  665.                   /* read position */
  666.                   a+=binput(a,linepos,200);
  667.                   sscanf(linepos,"%d",&pos);
  668.                   inthash_add((hash_chain**)cache->hash,cache->hash_size,line,pos);
  669.                 }
  670.               }
  671.               /* Not needed anymore! */
  672.               freet(cache->use);
  673.               cache->use=NULL;
  674.             }
  675. #endif
  676.           }
  677.         }
  678.       }  // taille cache>0
  679.     }  // cache precedent existe
  680.     
  681. #if DEBUGCA
  682.     printf("..create cache\n");
  683. #endif
  684.     // ouvrir caches actuels
  685.     cache->dat=fopen(fconcat(opt->path_log,"hts-cache/new.dat"),"wb");        
  686.     cache->ndx=fopen(fconcat(opt->path_log,"hts-cache/new.ndx"),"wb");        
  687.     // les deux doivent Ωtre ouvrables
  688.     if ((cache->dat==NULL) && (cache->ndx!=NULL)) {
  689.       fclose(cache->ndx);
  690.       cache->ndx=NULL;
  691.     }
  692.     if ((cache->dat!=NULL) && (cache->ndx==NULL)) {
  693.       fclose(cache->dat);
  694.       cache->dat=NULL;
  695.     }
  696.     
  697.     if (cache->ndx!=NULL) {
  698.       char s[256];
  699.       
  700.       cache_wstr(cache->dat,"CACHE-1.110");
  701.       fflush(cache->dat);
  702.       cache_wstr(cache->ndx,"CACHE-1.110");
  703.       fflush(cache->ndx);
  704.       //
  705.       time_gmt_rfc822(s);   // date et heure actuelle GMT pour If-Modified-Since..
  706.       cache_wstr(cache->ndx,s);        
  707.       fflush(cache->ndx);    // un petit fflush au cas o∙
  708.       
  709.       // supprimer old.lst
  710.       if (fexist(fconcat(opt->path_log,"hts-cache/old.lst")))
  711.         remove(fconcat(opt->path_log,"hts-cache/old.lst"));
  712.       // renommer
  713.       if (fexist(fconcat(opt->path_log,"hts-cache/new.lst")))
  714.         rename(fconcat(opt->path_log,"hts-cache/new.lst"),fconcat(opt->path_log,"hts-cache/old.lst"));
  715.       // ouvrir
  716.       cache->lst=fopen(fconcat(opt->path_log,"hts-cache/new.lst"),"wb");
  717.       {
  718.         filecreate_params tmp;
  719.         strcpy(tmp.path,opt->path_html);    // chemin
  720.         tmp.lst=cache->lst;                 // fichier lst
  721.         filenote("",&tmp);        // initialiser filecreate
  722.       }
  723.  
  724.       // test
  725.       // cache_writedata(cache->ndx,cache->dat,"//[TEST]//","test1","TEST PIPO",9);
  726.     }
  727.     
  728.   }
  729.   
  730. }
  731.   
  732.   
  733.   
  734.  
  735. // lire un fichier..
  736. char* lirefichier(char* fil) {
  737.   char* adr=NULL;
  738.   int len=0;
  739.   len=fsize(fil);
  740.   if (len>0) {  // existe
  741.     FILE* fp;
  742.     fp=fopen(fconv(fil),"rb");
  743.     if (fp!=NULL) {  // n'existe pas (!)
  744.       adr=(char*) malloct(len);
  745.       if (adr!=NULL) {
  746.         if ((int) fread(adr,1,len,fp)!=len) {    // fichier endommagΘ ?
  747.           freet(adr);
  748.           adr=NULL;
  749.         }
  750.       }
  751.       fclose(fp);
  752.     }
  753.   }
  754.   return adr;
  755. }
  756.  
  757. // Θcriture/lecture d'une chaεne sur un fichier
  758. // -1 : erreur, sinon 0
  759. int cache_wstr(FILE* fp,char* s) {
  760.   int i;
  761.   char buff[256];
  762.   i=strlen(s);
  763.   sprintf(buff,"%d\n",i);
  764.   if (fwrite(buff,1,strlen(buff),fp) != strlen(buff))
  765.     return -1;
  766.   if (i>0)
  767.   if ((int) fwrite(s,1,i,fp) != i)
  768.     return -1;
  769.   return 0;
  770. }
  771. void cache_rstr(FILE* fp,char* s) {
  772.   int i;
  773.   char buff[256];
  774.   linput(fp,buff,256);
  775.   sscanf(buff,"%d",&i);
  776.   if (i>0)
  777.     fread(s,1,i,fp);
  778.   *(s+i)='\0';
  779. }
  780. int cache_brstr(char* adr,char* s) {
  781.   int i;
  782.   int off;
  783.   char buff[256];
  784.   off=binput(adr,buff,256);
  785.   adr+=off;
  786.   sscanf(buff,"%d",&i);
  787.   if (i>0)
  788.     strncpy(s,adr,i);
  789.   *(s+i)='\0';
  790.   off+=i;
  791.   return off;
  792. }
  793. int cache_quickbrstr(char* adr,char* s) {
  794.   int i;
  795.   int off;
  796.   char buff[256];
  797.   off=binput(adr,buff,256);
  798.   adr+=off;
  799.   sscanf(buff,"%d",&i);
  800.   if (i>0)
  801.     strncpy(s,adr,i);
  802.   *(s+i)='\0';
  803.   off+=i;
  804.   return off;
  805. }
  806. /* idem, mais en int */
  807. int cache_brint(char* adr,int* i) {
  808.   char s[256];
  809.   int r=cache_brstr(adr,s);
  810.   if (r!=-1)
  811.     sscanf(s,"%d",i);
  812.   return r;
  813. }
  814. void cache_rint(FILE* fp,int* i) {
  815.   char s[256];
  816.   cache_rstr(fp,s);
  817.   sscanf(s,"%d",i);
  818. }
  819. int cache_wint(FILE* fp,int i) {
  820.   char s[256];
  821.   sprintf(s,"%d",(int) i);
  822.   return cache_wstr(fp,s);
  823. }
  824. void cache_rLLint(FILE* fp,LLint* i) {
  825.   char s[256];
  826.   cache_rstr(fp,s);
  827.   sscanf(s,LLintP,i);
  828. }
  829. int cache_wLLint(FILE* fp,LLint i) {
  830.   char s[256];
  831.   sprintf(s,LLintP,(LLint) i);
  832.   return cache_wstr(fp,s);
  833. }
  834. // -- cache --
  835.